package com.example.musictutor.services.runnables;

import java.io.IOException;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.util.Log;

import com.example.musictutor.domain.Note;
import com.example.musictutor.domain.SongNote;
import com.example.musictutor.services.KeyBoard;
import com.example.musictutor.services.playfunctionobserver.PlayFunctionObserver;
import com.example.musictutor.services.playfunctionobserver.PlayFunctions;
import com.example.musictutor.services.playfunctionobserver.PlaySubject;
import com.example.musictutor.views.KeyButton;

public class PlayNoteRunnable implements Runnable, OnPreparedListener,
		OnCompletionListener, OnErrorListener, PlayFunctionObserver {

	private Context context;
	private SongNote note;
	private MediaPlayer player;
	private PlaySubject playFunctionTopic;

	public PlayNoteRunnable() {
		super();
	}

	public PlayNoteRunnable(SongNote note, Context context) {
		super();
		this.note = note;
		this.context = context;
	}

	@Override
	public void run() {
		//KeyButton keyButton = KeyBoard.getInstance().getKeyButton(note);
		//keyButton.startPlayer();
		playNote(note);
		
		int duration = note.getEndPosition() - note.getStartPosition();
		int currentDuration = 0;

		Log.d("Play Note", "Name = " + note.getName());
		Log.d("Play Note", "Start = " + note.getStartPosition());
		Log.d("Play Note", "End = " + note.getEndPosition());

		while (currentDuration < duration) {
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			currentDuration += 20;
		}

		//keyButton.stopPlayer();
		stopPlayer();
	}

	private void playNote(Note note) {
		initializePlayer();
		Log.d("Key Player", "Initialized...");

		try {
			AssetFileDescriptor afd = getFileDescriptor(note.getResourceId());

			if (afd != null) {
				player.setDataSource(afd.getFileDescriptor(),
						afd.getStartOffset(), afd.getDeclaredLength());
				player.setOnPreparedListener(this);
				player.setOnCompletionListener(this);
				player.prepareAsync();
			}

		} catch (IllegalArgumentException e) {
			Log.e("Player", e.getStackTrace().toString());
		} catch (SecurityException e) {
			Log.e("Player", e.getStackTrace().toString());
		} catch (IllegalStateException e) {
			Log.e("Player", e.getStackTrace().toString());
		} catch (IOException e) {
			Log.e("Player", e.getStackTrace().toString());
		}
	}

	private void initializePlayer() {
		if (player != null) {
			player.release();
			player = null;
		}

		player = new MediaPlayer();
	}

	public void stopPlayer() {
		Log.d("Key Player", "Stopped...");
		if (player != null) {

			if (player.isPlaying())
				player.stop();

			player.release();
			player = null;
		}
	}

	private AssetFileDescriptor getFileDescriptor(int resourceId) {
		AssetFileDescriptor afd = null;
		afd = context.getResources().openRawResourceFd(resourceId);
		return afd;
	}

	@Override
	public void onPrepared(MediaPlayer mp) {
		mp.setVolume(0.65f, 0.65f);
		mp.start();
	}

	@Override
	public void onCompletion(MediaPlayer mp) {
		if (mp.isPlaying())
			mp.stop();

		mp.release();
		mp = null;
		player = null;
	}

	@Override
	public boolean onError(MediaPlayer mp, int what, int extra) {
		Log.e("Hein MediaPlayer", "ErrorListener Triggered");
		if (mp != null) {
			mp.release();
			mp = null;
			player = null;
		}
		return false;
	}

	@Override
	public void update() {

		int state = playFunctionTopic.getUpdate(this);

		switch (state) {
		case PlayFunctions.PLAY_PRESSED:
			resumeNote();
			break;
		case PlayFunctions.PAUSE_PRESSED:
			pauseNote();
			break;
		}
	}

	@Override
	public void setPlaySubject(PlaySubject subject) {
		this.playFunctionTopic = subject;
	}

	private void resumeNote() {
		if (player == null)
			return;

		if (player.isPlaying())
			player.start();

	}

	private void pauseNote() {

		if (player == null)
			return;

		if (!player.isPlaying())
			player.pause();
	}
}
